﻿// 引入所需的命名空间
using CoinTrader.Common;
using System;
using System.Threading;

namespace CoinTrader.Strategies
{
    /// <summary>
    /// 策略基类，所有交易策略都必须继承自此类
    /// 提供了定时执行、配置管理、日志记录等基础功能
    /// </summary>
    public abstract class StrategyBase : IDisposable
    {
        /// <summary>
        /// 定时器的间隔（毫秒）
        /// </summary>
        private const int TimerInterval = 1000;

        /// <summary>
        /// 标识定时器回调是否正在执行，防止并发执行
        /// </summary>
        private volatile bool timerRunning = false;

        /// <summary>
        /// 定时器实例，用于定期执行策略逻辑
        /// </summary>
        private Timer timer = null;

        /// <summary>
        /// 是否复盘模式（回测模式）
        /// 在复盘模式下不会启动实际的定时器
        /// </summary>
        public bool IsEmulationMode { get; set; }

        /// <summary>
        /// 策略是否启用
        /// 如果未启用，策略逻辑将不会执行
        /// </summary>
        public virtual bool Enable { get; set; }

        /// <summary>
        /// 策略是否正在执行中
        /// 主要用于界面状态显示
        /// </summary>
        public bool Executing { get; protected set; }

        /// <summary>
        /// 策略执行过程中产生的消息
        /// 可用于界面显示策略状态信息
        /// </summary>
        public string Message { get; protected set; } = string.Empty;

        /// <summary>
        /// 策略关联的交易对ID
        /// 用于标识该策略作用于哪个交易对
        /// </summary>
        public string InstId { get; protected set; } = "_strategy_undefine_inst_";

        /// <summary>
        /// 定时器内部回调方法
        /// 确保定时器回调不会并发执行
        /// </summary>
        /// <param name="state">定时器状态参数（未使用）</param>
        private void InnerOnTimer(object state)
        {
            // 只有在策略启用状态下才执行
            if (Enable)
            {
                // 防止定时器回调并发执行
                if (!timerRunning)
                {
                    timerRunning = true;
                    // 调用具体的定时器处理逻辑
                    this.OnTimer(TimerInterval);
                    timerRunning = false;
                }
            }
        }

        /// <summary>
        /// 定时器回调方法，在固定间隔执行策略逻辑
        /// 子类应重写此方法实现具体的策略逻辑
        /// </summary>
        /// <param name="deltaTime">距离上次执行的时间间隔（毫秒）</param>
        protected virtual void OnTimer(int deltaTime)
        {
            // 默认实现为空，子类需根据需要重写
        }

        /// <summary>
        /// 等待指定的毫秒数
        /// 通常用于等待客户端和服务器端的数据同步
        /// 注意：此方法会阻塞当前策略线程，但不影响其他策略执行
        /// 建议等待时间控制在5秒以内，长时间等待应使用倒计时方式
        /// </summary>
        /// <param name="milliseconds">要等待的毫秒数</param>
        protected virtual void Wait(int milliseconds)
        {
            // 使用线程睡眠实现等待
            Thread.Sleep(milliseconds);
        }

        /// <summary>
        /// 等待指定的秒数
        /// </summary>
        /// <param name="seconds">要等待的秒数</param>
        protected void Wait(float seconds)
        {
            // 将秒数转换为毫秒并执行等待
            Thread.Sleep((int)(seconds * 1000.0f));
        }

        #region 配置加载、保存

        /// <summary>
        /// 标识策略是否已有配置文件
        /// </summary>
        public bool HasConfig { get; private set; }

        /// <summary>
        /// 保存策略配置到配置文件
        /// </summary>
        /// <returns>返回错误信息，空字符串表示保存成功</returns>
        public string SaveConfig()
        {
            // 调用配置管理器保存当前策略配置
            string err = StrategyConfig.SaveStrategyConfig(this.InstId, this);
            // 更新配置状态：如果有配置或者保存无错误则标记为有配置
            this.HasConfig = HasConfig || string.IsNullOrEmpty(err);
            return err;
        }

        /// <summary>
        /// 从配置文件加载策略配置
        /// </summary>
        public void LoadConfig()
        {
            // 调用配置管理器加载当前策略配置
            this.HasConfig = StrategyConfig.LoadStrategyConfig(this.InstId, this);
        }
        #endregion

        /// <summary>
        /// 当策略参数发生变化时调用
        /// 子类可重写此方法处理参数变更逻辑
        /// </summary>
        public virtual void OnParamaterChanged()
        {
            // 默认实现为空
        }

        #region 写日志

        /// <summary>
        /// 记录调试级别日志
        /// </summary>
        /// <param name="log">日志内容</param>
        protected void LogDebug(string log)
        {
            // 通过日志管理器记录调试信息
            Logger.Instance.LogDebug(log);
        }

        /// <summary>
        /// 记录错误级别日志
        /// </summary>
        /// <param name="log">错误信息</param>
        protected void LogError(string log)
        {
            // 通过日志管理器记录错误信息
            Logger.Instance.LogError(log);
        }

        /// <summary>
        /// 记录异常信息
        /// </summary>
        /// <param name="ex">异常对象</param>
        protected void Log(Exception ex)
        {
            // 通过日志管理器记录异常信息
            Logger.Instance.LogException(ex);
        }
        #endregion

        /// <summary>
        /// 初始化策略
        /// 包括加载配置文件和启动定时器（非复盘模式下）
        /// </summary>
        /// <param name="instId">交易对ID</param>
        /// <returns>初始化是否成功</returns>
        public virtual bool Init(string instId)
        {
            // 设置交易对ID
            this.InstId = instId;
            // 加载策略配置
            this.LoadConfig();

            // 非复盘模式下启动定时器
            if (!IsEmulationMode)
            {
                timer = new Timer(InnerOnTimer, null, TimerInterval, TimerInterval);
            }

            return true;
        }

        /// <summary>
        /// 释放策略资源
        /// 实现IDisposable接口，用于清理定时器等资源
        /// </summary>
        public virtual void Dispose()
        {
            // 禁用策略
            this.Enable = false;
            // 释放定时器资源
            timer?.Dispose();
            timer = null;
        }
    }
}